<template>
  <el-scrollbar height="100vh">
    <div class="container">
      <el-affix :offset="1">
        <h1 class="title">点击Map弹窗 popup</h1>
      </el-affix>
      <div id="map" class="map-x" ref="mapBox"></div>
      <div ref="popup" class="popup">
        <div class="title">
          <h1>欢迎来到openlayers</h1>
          <el-icon class="icon-close" @click="closePopup"><close-bold /></el-icon>
        </div>
        <div class="content">The location you clicked was:<p>{{currentCoordinate}}</p></div>
      </div>
      <div class="codestyle"><Code /></div>
      <dl>
        <dt>overlay(叠加层)</dt>
        <dd>即叠加到地图上显示的元素， 关联了一个自定义的HTML元素，由一个单一的地图坐标点确定叠加位置。 与控件类似，但不同的是叠加元素不是在一个固定的屏幕位置上， 而是通过关联一个地图逻辑坐标点跟随地图移动，如标注点、popup等。</dd>
        <p>常用的属性：</p>
        <dt>element</dt>
        <dd>popup绑定的DOM元素。</dd>
        <dt>offset</dt>
        <dd>定位叠加层时使用的像素偏移量。数组中的第一个元素是水平偏移量。正值将覆盖向右移动。数组中的第二个元素是垂直偏移量。正值会使叠加层向下移动。</dd>
        <dt>position</dt>
        <dd>地图投影中的叠加位置。</dd>
        <dt>autoPan</dt>
        <dd>调用时平移地图 setPosition，使叠加层在当前视口中完全可见？boolean</dd>
        <dt>autoPanAnimation</dt>
        <dd>用于将叠加层平移到视图中的动画选项。此动画仅在autoPan启用时使用。</dd>
        <dt>autoPanMargin</dt>
        <dd>自动平移时叠加层和地图边界之间的边距（以像素为单位）。</dd>
        <dt>stopEvent</dt>
        <dd>不阻止默认事件，比如鼠标放到圆点上时，滚动鼠标滚轮，也可以缩放地图</dd>
        <dt>className</dt>
        <dd>CSS 类名。</dd>
      </dl>
    </div>
  </el-scrollbar>
</template>
<script>
import 'ol/ol.css'
import { Map, View } from 'ol'
import Tile from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ' // 引入XYZ地图格式
import Overlay from 'ol/Overlay'
import { toStringHDMS } from 'ol/coordinate'
import { toLonLat } from 'ol/proj'
import { onMounted, reactive, toRefs, ref } from 'vue-demi'
import { CloseBold } from '@element-plus/icons-vue'
import Code from './code.vue'
export default {
  setup () {
    const state = reactive({
      map: null,
      overlay: null,
      currentCoordinate: '',
      mapBox: ref(null),
      popup: ref(null)
    })

    onMounted(() => {
      init()
    })

    const init = () => {
      // 弹窗
      state.overlay = new Overlay({
        element: state.popup, // 弹窗标签，在html里
        autoPan: true, // 如果弹窗在底图边缘时，底图会移动
        autoPanAnimation: { // 底图移动动画
          duration: 250
        }
      })
      // 实例化地图
      state.map = new Map({
        target: state.mapBox,
        layers: [
          new Tile({
            name: 'defaultLayer',
            source: new XYZ({
              url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
            })
          })
        ],
        overlays: [state.overlay], // 把弹窗加入地图
        view: new View({
          projection: 'EPSG:4326',
          center: [116.41400, 39.91500],
          zoom: 12 // 地图缩放级别（打开页面时默认级别）
        })
      })
      mapClick()
    }
    // 添加地图点击事件
    const mapClick = () => {
      state.map.on('singleclick', evt => {
        console.log(state.overlay)
        const coordinate = evt.coordinate // 获取坐标
        const hdms = toStringHDMS(toLonLat(coordinate)) // 转换坐标格式
        state.currentCoordinate = hdms // 保存坐标点
        state.overlay.setPosition(coordinate)
      })
    }
    // 关闭弹窗
    const closePopup = () => {
      state.overlay.setPosition(undefined)
      state.currentCoordinate = null
    }
    return {
      ...toRefs(state),
      closePopup
    }
  },
  components: {
    CloseBold,
    Code
  }
}
</script>
<style lang="scss" scoped>
@import '../../css/main.scss';
.popup {
  width: 300px;
  height: 100px;
  background: #fff;
  position: absolute;
  top: -115px;
  left: -150px;
  box-sizing: border-box;
  border-radius: 10px;

  &::after {
    content: '';
    display: block;
    position: absolute;
    width: 20px;
    height: 20px;
    background: #fff;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%) rotate(45deg);
  }

  .icon-close {
    position: absolute;
    top: 0px;
    right: 8px;
  }

  .title{
    text-align: center;
    background-color: #e4e7ed;
    border-top-right-radius: 10px;
    border-top-left-radius: 10px;
  }

  .content {
    margin-top: 5px;
    line-height: 26px;
    font-size: 14px;
    padding-left: 10px;
  }
}
</style>
